import datetime
from enum import Enum
import os
from unicodedata import name
import bcrypt
import shelve
from pydantic import BaseModel
from faker import Faker
from threading import Timer

fake = Faker(locale='zh_CN')


def hash_password(password: str):
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())


# 考试状态
class ExamStatus(Enum):
    ARCHIVE = '已归档'
    REGISTERATION = '正在录入'
    INQUIRY = '开放查询'


# 考试科目枚举
class Subject(Enum):
    ADMIN = '管理员'
    CHINESE = '语文'
    MATH = '数学'
    ENGLISH = '英语'
    POLITICS = '政治'
    HISTORY = '历史'
    GEOGRAPHY = '地理'
    PHYSICS = '物理'
    CHEMISTRY = '化学'
    BIOLOGY = '生物'


# 考试
class Exam(BaseModel):
    time: datetime.date  # 考试日期
    status: ExamStatus  # 考试状态
    subjects: dict[Subject, dict[str, int]]  # 考试科目 -> 姓名 -> 分数


# 性别枚举
class Sex(Enum):
    Male = '男'
    Female = '女'


# 学生
class Student(BaseModel):
    id_number: str  # 身份证号
    phone_number: int  # 手机号
    sex: Sex  # 性别


# 教师
class Teacher(BaseModel):
    name: str  # 姓名
    id_number: str  # 身份证号
    password: bytes  # bcrypt 哈希后的密码
    phone_number: int  # 手机号
    sex: Sex  # 性别
    subject: Subject  # 所教的科目
    classes: list[str]  # 所教的班级


# Data
class Data(BaseModel):
    api_version: str  # 后端 API 版本号
    # exams 考试列表，以届(int)为键，每届有不同名字(str)的考试(Exam)
    exams: dict[int, dict[str, Exam]]
    # students 学生列表，以届(int)为键，每届有不同名字(str)的班级(dict[str, Student])
    # 每个班级有不同名字(str)的学生(Student)
    students: dict[int, dict[str, dict[str, Student]]]
    # teachers 教师列表，以届(int)为键，每届有不同名字(str)的老师(Teacher)
    teachers: dict[int, dict[str, Teacher]]


data = Data(
    api_version='1.3.2',
    exams={},
    students={},
    teachers={}
)


dataBak = Data(
    api_version='1.3.2',
    exams={
        2021: {
            '高一2月月考': Exam(
                time=datetime.datetime.utcnow(),
                status=ExamStatus.ARCHIVE,
                subjects={
                    Subject.CHINESE: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    },
                    Subject.MATH: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    },
                    Subject.ENGLISH: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    }
                },
            ),
            '高一3月月考': Exam(
                time=datetime.datetime.utcnow(),
                status=ExamStatus.INQUIRY,
                subjects={
                    Subject.CHINESE: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    },
                    Subject.MATH: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    },
                    Subject.ENGLISH: {
                        '杨辉': fake.random_number(digits=2),
                        '唐娜': fake.random_number(digits=2),
                        '瞿桂香': fake.random_number(digits=2),
                        '万玉英': fake.random_number(digits=2),
                    }
                },
            ),
        },
        2020: {
            '高二2月月考': Exam(
                time=datetime.datetime.utcnow(),
                status=ExamStatus.ARCHIVE,
                subjects={
                    Subject.CHINESE: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    },
                    Subject.MATH: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    },
                    Subject.ENGLISH: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    }
                },
            ),
            '高二3月月考': Exam(
                time=datetime.datetime.utcnow(),
                status=ExamStatus.INQUIRY,
                subjects={
                    Subject.CHINESE: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    },
                    Subject.MATH: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    },
                    Subject.ENGLISH: {
                        '廖俊': fake.random_number(digits=2),
                        '宋玲': fake.random_number(digits=2),
                        '刘涛': fake.random_number(digits=2),
                        '庞佳': fake.random_number(digits=2),
                    }
                },
            ),
        },
    },
    students={
        2021: {
            '一班': {
                '杨辉': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Male,
                ),
                '唐娜': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Female,
                ),
            },
            '二班': {
                '瞿桂香': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Male,
                ),
                '万玉英': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Female,
                ),
            },
        },
        2020: {
            '一班': {
                '廖俊': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Male,
                ),
                '宋玲': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Female,
                ),
            },
            '二班': {
                '刘涛': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Male,
                ),
                '庞佳': Student(
                    id_number=fake.ssn(),
                    phone_number=fake.phone_number(),
                    sex=Sex.Female,
                ),
            },
        },
    },
    teachers={
        0: {
            'admin': Teacher(
                name='admin',
                id_number=0,
                password=hash_password('adminpassword'),
                phone_number=0,
                sex=Sex.Male,
                subject=Subject.ADMIN,
                classes=[],
            ),
        },
        2021: {
            '张东': Teacher(
                name='张东',
                id_number=fake.ssn(),
                password=hash_password('password1'),
                phone_number=fake.phone_number(),
                sex=Sex.Male,
                subject=Subject.CHINESE,
                classes=['一班', '二班'],
            ),
            '王想': Teacher(
                name='王想',
                id_number=fake.ssn(),
                password=hash_password('password2'),
                phone_number=fake.phone_number(),
                sex=Sex.Male,
                subject=Subject.MATH,
                classes=['一班', '二班'],
            ),
        },
    },
)


def save_data():
    with shelve.open('data.db') as d:
        d['data'] = data
        d.sync()


if os.path.exists('data.db'):
    with shelve.open('data.db') as d:
        data = d['data']
else:
    data = dataBak
    save_data()

# 定时器防抖，防止请求过多导致硬盘写入频繁


timer = Timer(2, save_data)


def flush():
    global timer
    timer.cancel()
    timer = Timer(2, save_data)
    timer.start()
